iT邦幫忙

2023 iThome 鐵人賽

DAY 8
1

嗨我是k66,久等了終於可以進到UEFI程式碼階段~今天實作Day3的No Pig Killing,這次不用asm而用efi。如Day5提的UEFI開機流程,除Security部分,其餘皆使用C語言,故以下開發我們皆使用C語言。我們會在EDK2上開發UEFI Application,故會與標準C寫法不同。不知道EDK2的人請看[註1]。要輸出No Pig Killing,標準C寫法是:

#include <stdio.h>
int main{
    printf("No Pig Killing!\n");
    return 0;
}

UEFI APPICATION分3類:UefiMainmainShellAppMain,此三種皆能在UEFI Shell上運行。本篇會以第一類UefiMain實作,然而此類做法的C語言是不支援標準函數庫stdio.h的,支援的做法是第二類main,將在Day10實作。繼續回到本日主題,EDK2程式碼龐大,重點不外乎:

1. 先建立一資料夾: XXPkg // 沒硬性規定,以此命名的好處是未來看到Pkg字樣就知道是個資料夾
2. 在資料夾內建立: XX.c
3. 在資料夾內建立: XX.inf // 注意: inf檔名需與c檔名相同
4. 在資料夾內建立: XXPkg.dsc // 注意: dsc檔名需與資料夾檔名相同,故要有*Pkg*
5. 開始寫第二步到第四步的檔案內容。
6. 修改Conf\target.txt
7. 執行

以下步驟強烈建議讀者跟著一起實作!

程式碼連結

  • 首先是根據上述重點五步驟,我們要寫一隻NoPigKill.efi就必須:
1. 建一資料夾: NoPigKillPkg
2. 建: NoPigKill.c
3. 建: NoPigKill.inf
4. 建: NoPigKillPkg.dsc // 注意要有*Pkg*
  • 5-1. 接著撰寫NoPigKill.c,以下為最少必填:
#include<Uefi.h>         // Uefi所需最基本庫
#include<Library/UefiLib.h>   // Print庫
EFI_STATUS             // 宣告函數的型別,實作UEFI APPICATION使用EFI_STATUS是硬性規定。 
UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) // 宣告UefiMain()函式,名稱要與INF檔的ENTRY_POINT名稱一致。       
{
    Print(L"No pig killing!\n");  // 輸出字串,L: Long
    return 0;            // C語言函數一定得有返回值
}
  • 5-2. 撰寫NoPigKill.inf,以下為最少必填:
[Defines]
    INF_VERSION = 0x00010006                  // 建議此版本
    BASE_NAME = NoPigKill                // c的檔名    
    FILE_GUID = 812f9633-219f-4e1e-b665-a1252870bfad // 需一GUID,請去guidgen.com生成一組
    MODULE_TYPE = UEFI_APPLICATION           // 使我們能在UEFI shell執行之
    ENTRY_POINT = UefiMain                            // 填NoPigKill.c的進入點函數名稱

[Sources]
    NoPigKill.c                              // 請Compiler執行NoPigKill.c                

[Packages]
    MdePkg/MdePkg.dec                        // 使用到的Library來自MdePkg

[LibraryClasses]
    UefiApplicationEntryPoint         // 使用到的Library
    UefiLib                   // 使用到的Library,Print()
  • 5-3. 撰寫NoPigKillPkg.dsc,以下為最少必填:

[LibraryClasses]就是要寫這麼多...

[Defines]
    PLATFORM_NAME = NoPigKillPkg                          // 資料夾名稱
    PLATFORM_GUID = f2b2247d-b9ce-4ced-a58c-a534925ab4e3  // 需一GUID,需與inf的不同
    PLATFORM_VERSION = 0.1                                // 需給一版本號,自訂
    DSC_SPECIFICATION = 0x00010005                        // 建議此版本
    SUPPORTED_ARCHITECTURES = X64                         // X64表示x86的64位元
    BUILD_TARGETS = DEBUG|RELEASE                         // DEBUG或RELEASE


// [LibraryClasses]寫所有需要用到的inf,通常先填UefiLib和UefiApplicationEntryPoint,
// 及c有用到的函式如Print()的BasePrintLib,其他就看報錯缺什麼填什麼。寫UEFI APPLICATION最痛苦之處~
[LibraryClasses]                                             
    UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
    UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
    PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
    PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
    MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
    DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
    BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
    BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
    UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
    DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
    UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
    RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
    DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
    
[Components]
    NoPigKillPkg/NoPigKill.inf  // NoPigKill.inf位置
    1. 改C:\edk2space\edk2\Conf\target.txt:
ACTIVE_PLATFORM       = NoPigKillPkg/NoPigKillPkg.dsc
    1. 完成c、inf、dsc與修改target.txt後,在C:\edk2space\edk2\下,依序執行:
k66run1.bat
edk2setup.bat Rebuild
build     // 看到Done表示編譯成功,後續可將efi[註2]放至QEMU執行(Day7有完整做法)

畫面如下:
https://ithelp.ithome.com.tw/upload/images/20230914/201618289vLfJ9OieN.png

恭喜完成!我們明天見!


[註1] EDK2是現代實現UEFI的跨平台開發環境,前兩篇文下載工具列表就有EDK2。
[註2] C:\edk2space\edk2\Build\NoPigKillPkg\DEBUG_VS2019\X64\NoPigKill.efi


自我挑戰2

Day3實作OinkBootloader.asm時,豬油博士說x86與ARM的組合語言差異非常大。
想想看本日Day8實作NoPigKill.efi時,用的是C語言,
在x86和ARM下efi,程式碼差異大嗎?為什麼?


上一篇
【Day 7】UEFI安裝環境—附圖保證安裝到好!(下)
下一篇
【Day 9】完全理解UEFI格式!Module、INF、Package、DSC、DEC
系列文
世界第一簡單的UEFI,實作打造自己的開機畫面31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言